﻿using System;
using System.ComponentModel;
using System.Linq;
using System.Xml.Serialization;
using Microsoft.WowAddonStudio.FrameXml.Serialization.LayoutFrames;

namespace Microsoft.WowAddonStudio.FrameXml.Serialization.Support
{
    public class LayerList : InheritableList<Layer>
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="LayerList"/> class.
        /// </summary>
        /// <param name="owner">The property bag that owns the layer list.</param>
        /// <param name="propertyName">Name of the property.</param>
        public LayerList(PropertyBag owner, string propertyName)
            : base(owner, propertyName)
        {
        }

		/// <summary>
		/// Gets or sets a value indicating whether inheritance is enabled.
		/// </summary>
		/// <remarks>
		/// The value is propagated to all non-inherited children.
		/// </remarks>
		[XmlIgnore]
		[Browsable(false)]
		public override bool InheritanceEnabled
		{
			get { return base.InheritanceEnabled; }
			set
			{
				base.InheritanceEnabled = value;
				foreach (Layer layer in list)
				{
					layer.InheritanceEnabled = value;
				}
			}
		}

        /// <summary>
        /// Adds a layered layout frame.
        /// </summary>
        /// <param name="frame">The layered layout frame to add.</param>
        public void AddLayeredLayoutFrame(LayeredLayoutFrame frame)
        {
            if (frame == null)
                throw new ArgumentNullException("frame");

            // Add the frame to the layer
        	if(list.SingleOrDefault(item => item.Items.Contains(frame)) == null)
        	{
				// Find or create the layer for the frame
				Layer layer = list.SingleOrDefault(l => l.Level == frame.DrawLayer);
				if (layer == null)
				{
					layer = new Layer { Level = frame.DrawLayer };
					this.Add(layer);
				}
        		layer.Items.Add(frame);
        	}
        }

        /// <summary>
        /// Removes a layered layout frame.
        /// </summary>
        /// <param name="frame">The layered layout frame to remove.</param>
        public void RemoveLayeredLayoutFrame(LayeredLayoutFrame frame)
        {
            if (frame == null)
                throw new ArgumentNullException("frame");

            // Find the layer of the frame
            Layer layer = list.SingleOrDefault(l => l.Level == frame.DrawLayer);
            if (layer != null)
            {
                // Remove the frame
                layer.Items.Remove(frame);

                // If the layer is now empty, remove layer
                if (layer.Items.UninheritedCount == 0)
                    this.Remove(layer);
            }
        }

		/// <summary>
		/// Determines whether [contains layered layout frame] [the specified frame].
		/// </summary>
		/// <param name="frame">The frame.</param>
		/// <returns>
		/// 	<c>true</c> if [contains layered layout frame] [the specified frame]; otherwise, <c>false</c>.
		/// </returns>
        public bool ContainsLayeredLayoutFrame(LayeredLayoutFrame frame)
        {
            if (frame != null)
            {
                // Find the layer of the frame
                Layer layer = list.SingleOrDefault(l => l.Level == frame.DrawLayer);
                if (layer != null)
                {
                    return layer.Items.Contains(frame);
                }
            }

            return false;
        }

		/// <summary>
		/// Determines whether the specified frame contains frame.
		/// </summary>
		/// <param name="frame">The frame.</param>
		/// <returns>
		/// 	<c>true</c> if the specified frame contains frame; otherwise, <c>false</c>.
		/// </returns>
		public bool ContainsFrame(LayeredLayoutFrame frame)
		{
			if (frame != null)
			{
				foreach (Layer layerItem in list)
					if (layerItem.Items.Contains(frame)) return true;
                
				InheritableList<Layer> inheritedList = InheritedList;
				if(inheritedList != null)
				{
					foreach (Layer layer in inheritedList)
					{
						if (layer.Items.Contains(frame)) return true;
					}
				}
			}

			return false;
		}


        /// <summary>
        /// Gets the layer.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public Layer GetLayer(string name)
        {
            foreach (Layer layerItem in list)
            {
                var frame = layerItem.Items.SingleOrDefault(i => i.Name == name);
                if (frame != null)
                    return layerItem;
            }

            return null;
        }
    }
}
